#include "raster-fixed.h"

int __cdecl FixedToAscii(Fixed val, char *buf, int bufsz, int width)
{
    int pow10[9] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
    int whole, frac;
    int fracdec = 0;
    int bufrem = bufsz;
    int i = 1; /* print at least the zero */
    if(bufrem < 2)
        return 0;

    if(val < 0)
    {
        val = -val;
        *buf = '-';
        ++buf;
        --bufrem;
    }
    whole = val >> 16;
    frac = val & 0xFFFF;

    /* write the whole number portion into the buffer.
        essentially atoi(whole, buf, 10) */
    while(whole > pow10[i])
        i++;
    while(bufrem > 1 && i > 0)
    {
        *buf = (char)('0' + whole / pow10[i-1]);
        whole = whole % pow10[i-1];
        ++buf;
        --bufrem;
        --i;
    }
    if(width > 0 && bufrem > 2)
    {
        /*
            Each bit is 1/2 of the value of the bit above that, such that:
            1000 0000 0000 0000 = .5
            0100 0000 0000 0000 = .25
            0010 0000 0000 0000 = .125
            0001 0000 0000 0000 = .0625
            etc

            so we compute a running sum of the value of each set pixel

            32-bit integers can only hold a value up to 4.294967296 x 10^9,
            so we can only write 9 digits
        */
        int testbit = 0x8000; /* highest bit in fractional part */
        int bitval = 5; /* 1/2 */
        int len = 0;
        int first = -1;
        while(frac > 0 && width > 0 && testbit > 0 && len < 9)
        {
            fracdec *= 10;
            if(frac & testbit)
            {
                if(first < 0)
                {
                    first = len;
                }
                fracdec += bitval;
            }

            frac &= ~testbit;
            bitval *= 5;
            testbit >>= 1;
            len++;
            width--;
        }
        /* write the decimal point */
        *buf = '.';
        ++buf;
        --bufrem;
        /* convert to ascii - essentially atoi(fracdec, buf, 10) */
        while(bufrem > 1 && len > 0)
        {
            *buf = (char)('0' + fracdec / pow10[len-1]);
            fracdec = fracdec % pow10[len-1];
            buf++;
            --bufrem;
            --len;
        }
        /* print trailing zeroes */
        while(width > 1 && bufrem > 1)
        {
            *buf = '0';
            ++buf;
            --bufrem;
            --width;
        }
    }
    *buf = 0;
    return bufsz - bufrem;
}
